#include "decoder.h"
#include "detector.h"
#include "imagereader.h"
#include "common/bch.h"
#include "common/masking.h"
#include "common/symbol.h"
#include "common/versions.h"
#include "common/stringutils.h"
#include "common/alphanumerictable.h"
#include "common/errorcorrection.h"
#include "generate/formatinfo.h"

#include <QByteArray>
#include <QImage>
#include <vector>
#include <cmath>

#include <QDebug>

namespace qrcode {


Decoder::Decoder()
{
    dataInfo = "";
}

std::vector<std::vector<int> > Decoder::ToCodewords(std::vector<int> &bits)
{
    std::vector<std::vector<int> > _block;
    std::vector<int> _word;

    int n = 0;
    for(int i = 0; i < bits.size(); i += 8){
        for(int j = 0; j < 8; j++){
            _word.push_back(bits.at(n++));
        }
        _block.push_back(_word);
        _word.clear();
    }
    return _block;
}

void Decoder::RemoveRemainderBits(std::vector<int> &databits, int length)
{
    if(length > 0){
        std::vector<int> vec;
        for(int i = 0; i < databits.size()-length; i++){
            vec.push_back(databits.at(i));
        }
        databits = vec;
    }
}

datapairs Decoder::HandleDataBits(std::vector<int> databits)
{
    //去除末尾填充信息
    Versions *qVer = new Versions();
    int remainderLength = qVer->GetGetRemainderBitsLength(version);
    RemoveRemainderBits(databits, remainderLength);
    StringUtils::PRINT("信息数据位长度：", int(databits.size()));

    //1.数据流转换为码字
    std::vector<std::vector<int> > _block = ToCodewords(databits);
    std::vector<int> breakInfo = qVer->GetBreakInfo(version, errorlevel);

    int n = 0;
    std::vector<std::vector<std::vector<int> > > colls;
    std::vector<std::vector<int> > coll;

    StringUtils::PRINT("第一组块数：", int(breakInfo.at(1)));
    StringUtils::PRINT("第一组每块码字数：", int(breakInfo.at(2)));
    StringUtils::PRINT("第二组块数：", int(breakInfo.at(3)));
    StringUtils::PRINT("第二组每块码字数：", int(breakInfo.at(4)));
    StringUtils::PRINT("每块纠错码字数：", int(breakInfo.at(0)));
    int ll = breakInfo.at(2) > breakInfo.at(4) ? breakInfo.at(2) : breakInfo.at(4);
    for(int i = 0; i < ll; i++) {
        if(i < breakInfo.at(2)){
            //StringUtils::PRINT("group1");
            for(int j = 0; j < breakInfo.at(1); j++){
                coll.push_back(_block.at(n++));
            }
        } else {
            //第一组每块的长度小于第二组
            //在此列对应的第一组每块最后补空块，使其与第二组每块的长度相同
            for(int j = 0; j < breakInfo.at(1); j++){
                coll.push_back({0});
            }
        }

        if(i < breakInfo.at(4)){
            //StringUtils::PRINT("group2");
            for(int j = 0; j < breakInfo.at(3); j++){
                coll.push_back(_block.at(n++));
            }
        }

        colls.push_back(coll);
        coll.clear();
    }

    std::vector<std::vector<std::vector<int> > > g1;
    std::vector<std::vector<std::vector<int> > > g2;
    std::vector<std::vector<int> > b;
    std::vector<std::vector<int> > _b;
    //填充第一组的每块的数据
    for(int i = 0; i < breakInfo.at(1); i++){
        for(int j = 0; j < breakInfo.at(2); j++){
            _b = colls.at(j);
            b.push_back(_b.at(i));
        }

        g1.push_back(b);
        b.clear();
    }

    //填充第二组中每块的数据
    for(int i = breakInfo.at(1); i < breakInfo.at(1)+breakInfo.at(3); i++){
        for(int j = 0; j < breakInfo.at(4); j++){
            _b = colls.at(j);
            b.push_back(_b.at(i));
        }
        g2.push_back(b);
        b.clear();
    }

    //合并第一组的数据和第二组的块数据
    for(int i = 0; i < g2.size(); i++){
        b = g2.at(i);
        g1.push_back(b);
    }

    int l = _block.size();
    StringUtils::PRINT("读取信息数据: ", n, l);

    //纠错码字
    int n1 = n;
    std::vector<std::vector<std::vector<int> > > EC;
    std::vector<std::vector<int> > _ec;
    int _c;
    for(int i = 0; i < breakInfo.at(1)+breakInfo.at(3); i++){
        int k = n++;
        for(int j = 0; j < breakInfo.at(0); j++){
            _ec.push_back(_block.at(k+j*(breakInfo.at(1)+breakInfo.at(3))));
        }
        EC.push_back(_ec);
        _c = _ec.size();
        _ec.clear();
    }

    StringUtils::PRINT("数据块数：", int(g1.size()));
    StringUtils::PRINT("纠错块数：", int(EC.size()));
    StringUtils::PRINT("纠错码字数：", int(_c*EC.size()));
    StringUtils::PRINT("读取纠错数据: ", n1+_c*EC.size(), l);

    datapairs codespairs;
    n1 = 0;
    for(int i = 0; i < g1.size(); i++){
        codespairs.push_back(std::make_pair(g1.at(i), EC.at(i)));
    }

    return codespairs;
}

void Decoder::RemovePadBits(std::vector<std::vector<int> > &data)
{
    int t = 0;
    for(int i = data.size()-1; i >= 0; i--){
        if(IsPadBits(data.at(i))){
            //StringUtils::PRINT("附加值");
            t++;
        } else {
            break;
        }
    }

    std::vector<std::vector<int> > vec;
    for(int i = 0; i < data.size()-t; i++){
        vec.push_back(data.at(i));
    }
    data = vec;
}

bool Decoder::IsPadBits(std::vector<int> &data)
{
    bool b1 = true;
    bool b2 = true;
    std::vector<int> padBytes_1{1, 1, 1, 0, 1, 1, 0, 0};
    std::vector<int> padBytes_2{0, 0, 0, 1, 0, 0, 0, 1};
    int x1;
    int x2;
    for(int i = 0; i < 8; i++){
        x1 = data.at(i);
        x2 = padBytes_1.at(i);
        //StringUtils::PRINT("x1: ", x1);
        //StringUtils::PRINT("x2: ", x2);
        if(x1 != x2){
            //StringUtils::PRINT("不等于附加值");
            b1 = false;
            break;
        }
    }

    for(int i = 0; i < 8; i++){
        x1 = data.at(i);
        x2 = padBytes_2.at(i);
        if(x1 != x2){
            //StringUtils::PRINT("不等于附加值");
            b2 = false;
            break;
        }

    }

    if(b1 || b2){
        return true;
    } else {
        return false;
    }
}

void Decoder::GetDataLength(std::vector<int> &databits, int x)
{
    Versions *qVer = new Versions();
    count = qVer->GetCharacterCount(mode, version);
    //StringUtils::PRINT("计数指示符个数：", count);

    std::vector<int> countv;
    for(int i = x; i < x+count; i++){
        countv.push_back(databits.at(i));
    }
    StringUtils::PRINT("字符计数指示符：", countv);
    int _l;
    dataLength = 0;
    for(int i = 0; i < countv.size(); i++){
        _l = countv.at(i);
        dataLength += _l * int(pow(2, count-i-1));
    }
    StringUtils::PRINT("原始数据字节长度：", dataLength);
}

void Decoder::RecoveryDataNUM(std::vector<int> &databits)
{
    GetDataLength(databits, 4);

    int bitlength = 10*(dataLength / 3);
    int _t1 = dataLength % 3;
    if(_t1 == 1){
        bitlength += 4;
    } else if(_t1 == 2){
        bitlength += 7;
    }
    StringUtils::PRINT("数字编码的位流长度：", bitlength);
    std::vector<int> newdatabits;
    for(int i = 0; i < bitlength; i++){
        newdatabits.push_back(databits.at(i+4+count));
    }

    std::vector<std::vector<int>> _data;
    std::vector<int> _data1;
    int n = 0;
    for(int i = 0; i < bitlength/10; i++){
        for(int j = 0; j < 10; j++){
            _data1.push_back(newdatabits.at(n++));
        }
        _data.push_back(_data1);
        _data1.clear();
    }
    if(bitlength%10 != 0){
        for(int i = 0; i < bitlength%10; i++){
            _data1.push_back(newdatabits.at(n++));
        }
        _data.push_back(_data1);
    }

    for(int i = 0; i < _data.size(); i++){
        dataInfo += ToIntStr(_data.at(i));
    }
    StringUtils::PRINT("解码结果：" + QString::fromStdString(dataInfo));
}

void Decoder::RecoveryDataAN(std::vector<int> &databits)
{
    GetDataLength(databits, 4);

    int bitlength = 11*(dataLength / 2);
    int _t1 = dataLength % 2;
    if(_t1 == 1){
        bitlength += 6;
    }

    StringUtils::PRINT("字母数字编码的位流长度：", bitlength);
    std::vector<int> newdatabits;
    for(int i = 0; i < bitlength; i++){
        newdatabits.push_back(databits.at(i+4+count));
    }

    std::vector<std::vector<int>> _data;
    std::vector<int> _data1;
    int n = 0;
    for(int i = 0; i < bitlength/11; i++){
        for(int j = 0; j < 11; j++){
            _data1.push_back(newdatabits.at(n++));
        }
        _data.push_back(_data1);
        _data1.clear();
    }
    if(bitlength%11 != 0){
        for(int i = 0; i < bitlength%11; i++){
            _data1.push_back(newdatabits.at(n++));
        }
        _data.push_back(_data1);
    }

    for(int i = 0; i < _data.size(); i++){
        dataInfo += ToANStr(_data.at(i));
    }
    StringUtils::PRINT("解码结果：" + QString::fromStdString(dataInfo));
}

void Decoder::RecoveryDataByte(std::vector<int> &databits)
{
    GetDataLength(databits, 4);

    int bitlength = 8*dataLength;

    StringUtils::PRINT("二进制编码的位流长度：", bitlength);
    std::vector<int> newdatabits;
    for(int i = 0; i < bitlength; i++){
        newdatabits.push_back(databits.at(i+4+count));
    }

    std::vector<std::vector<int>> _data;
    std::vector<int> _data1;
    int n = 0;
    for(int i = 0; i < bitlength/8; i++){
        for(int j = 0; j < 8; j++){
            _data1.push_back(newdatabits.at(n++));
        }
        _data.push_back(_data1);
        _data1.clear();
    }

    for(int i = 0; i < _data.size(); i++){
        dataInfo += ToByteStr(_data.at(i));
    }
    StringUtils::PRINT("解码结果：" + QString::fromStdString(dataInfo));
}

void Decoder::RecoveryDataECI(std::vector<int> &databits)
{
    GetDataLength(databits, 16);

    int bitlength = 8*dataLength;

    StringUtils::PRINT("ECI编码的位流长度：", bitlength);
    std::vector<int> newdatabits;
    for(int i = 0; i < bitlength; i++){
        newdatabits.push_back(databits.at(i+16+count));
    }

    std::vector<std::vector<int>> _data;
    std::vector<int> _data1;
    int n = 0;
    for(int i = 0; i < bitlength/8; i++){
        for(int j = 0; j < 8; j++){
            _data1.push_back(newdatabits.at(n++));
        }
        _data.push_back(_data1);
        _data1.clear();
    }


    QByteArray ba;
    //std::string str1 = "";
    for(int i = 0; i < _data.size(); i++){
         ba += ToUnicodeStr(_data.at(i));
    }
    QString str = QString::fromLocal8Bit(ba);
    dataInfo  = str.toStdString();
    StringUtils::PRINT("解码结果：" + QString::fromStdString(dataInfo));
}

void Decoder::Decoding()
{
    //1.探测图像信息
    Detector *pdet = new Detector();
    pdet->SimpleProcess(imagefile);
    QImage img = pdet->getPixelImage();

    //2.获得数据流
    ImageReader *preader = new ImageReader();
    preader->setImage(img);
    preader->ReadFormatVertionBits();

    std::pair<std::vector<int>, std::vector<int>> formats = preader->getFormatbits();
    std::pair<std::vector<int>, std::vector<int>> versions = preader->getVersionbits();

    //3.格式版本信息译码
    DecodeFormat(formats.first);

    std::vector<int> ver = versions.first;
    if(ver.size() > 0){
        DecodeVersion(versions.first);
    } else {
        version = preader->getVersion();
    }

    StringUtils::PRINT("纠错等级：", errorlevel);
    StringUtils::PRINT("掩模模式：", maskNum);
    StringUtils::PRINT("版本：", version);


    //5.数据译码
    preader->setImage(img);
    preader->setMaskNum(maskNum);
    preader->ReadBits();
    DecodeData(preader->getDatabitstream());
}

void Decoder::DecodeData(std::vector<int> databits)
{
    //StringUtils::PRINT("数据流：", databits);
    //获得块数据
    datapairs datas = HandleDataBits(databits);

    //纠错处理
    ErrorCorrection *perror = new ErrorCorrection();
    datapair data;
    for(int i = 0; i < datas.size(); i++){
        data = datas.at(i);
        if(perror->IsCorrect(data.first, data.second)){
            //StringUtils::PRINT("数据--", data.first);
        }
    }
    std::vector<std::vector<int>> correctdata;
    std::vector<std::vector<int>> _d;
    for(int i = 0; i < datas.size(); i++){
        data = datas.at(i);
        _d = data.first;
        for(int j = 0; j < _d.size(); j++){
            correctdata.push_back(_d.at(j));
        }
    }

    StringUtils::PRINT("数据码字数：", int(correctdata.size()));

    //去除附加字段
    RemovePadBits(correctdata);

    std::vector<int> correctdatabits;
    std::vector<int> tmp_databits;
    for(int i = 0; i < correctdata.size(); i++){
        tmp_databits = correctdata.at(i);
        for(int j = 0; j < tmp_databits.size(); j++){
            correctdatabits.push_back(tmp_databits.at(j));
        }
    }

    //StringUtils::PRINT("原始数据码字数：", int(correctdata.size()));

    mode = "";
    for(int i = 0; i < 4; i++){
        mode = mode + ToChar(correctdatabits.at(i));
    }

    StringUtils::PRINT("模式：" + QString::fromStdString(mode));

    if(mode == MODEL_INDICATOR_NUM){
        RecoveryDataNUM(correctdatabits);
    } else if(mode == MODEL_INDICATOR_AN){
        RecoveryDataAN(correctdatabits);
    } else if(mode == MODEL_INDICATOR_BYTE){
        RecoveryDataByte(correctdatabits);
    } else if(mode == MODEL_INDICATOR_ECI){
        RecoveryDataECI(correctdatabits);
    }
}

void Decoder::DecodeFormat(std::vector<int> format)
{
    //1.去除掩模
    FormatInfo *pformat = new FormatInfo();
    pformat->RemoveMask(format);
    StringUtils::PRINT("消除掩码后的格式信息：", format);

    //2.判断格式信息是否正确
    BCH *pbch = new BCH();
    std::vector<int> vec;
    if(pbch->IsCorrect15_5(format)){
        StringUtils::PRINT("格式信息正确");
    } else {
        StringUtils::PRINT("格式信息错误");
    }
    for(int i = 0; i < 5; i++){
        vec.push_back(format.at(i));
    }

    int cc = vec.at(0)*10 + vec.at(1);
    switch (cc) {
    case 1:
        errorlevel = ERROR_CORRECTION_LEVEL_L;
        break;
    case 0:
        errorlevel = ERROR_CORRECTION_LEVEL_M;
        break;
    case 11:
        errorlevel = ERROR_CORRECTION_LEVEL_Q;
        break;
    case 10:
        errorlevel = ERROR_CORRECTION_LEVEL_H;
        break;
    default:
        break;
    }

    cc = vec.at(2)*100 + vec.at(3)*10 + vec.at(4);
    switch (cc) {
    case 0:
        maskNum = 0;
        break;
    case 1:
        maskNum = 1;
        break;
    case 10:
        maskNum = 2;
        break;
    case 11:
        maskNum = 3;
        break;
    case 100:
        maskNum = 4;
        break;
    case 101:
        maskNum = 5;
        break;
    case 110:
        maskNum = 6;
        break;
    case 111:
        maskNum = 7;
        break;
    default:
        break;
    }
}

void Decoder::DecodeVersion(std::vector<int> ver)
{
    //2.判断格式信息是否正确
    BCH *pbch = new BCH();
    std::vector<int> vec;
    if(pbch->IsCorrect18_6(ver)){
        StringUtils::PRINT("版本信息正确");
    } else {
        StringUtils::PRINT("版本信息错误");
    }

    for(int i = 0; i < 6; i++){
        vec.push_back(ver.at(i));
    }

    version = vec.at(0)*32 + vec.at(1)*16 + vec.at(2)*8
                + vec.at(3)*4 + vec.at(4)*2 + vec.at(5);
}

char Decoder::ToChar(int x)
{
    if(x == 1){
        return '1';
    } else if(x == 0){
        return '0';
    }
}

std::__cxx11::string Decoder::ToIntStr(std::vector<int> vec)
{
    int n = vec.size();

    int num = 0;
    for(int i = 0; i < n; i++){
        num = num + int(vec.at(i))*int(pow(2, n-i-1));
    }
    QString str = QString::number(num, 10);
    if(n == 10){
        while(str.length() < 3){
            str = '0' + str;
        }
    } else if(n == 7){
        while(str.length() < 2){
            str = '0' + str;
        }
    }
    return str.toStdString();
}

std::__cxx11::string Decoder::ToANStr(std::vector<int> vec)
{
    int n = vec.size();

    int num = 0;
    for(int i = 0; i < n; i++){
        num = num + int(vec.at(i))*int(pow(2, n-i-1));
    }
    AlphanumericTable *pANT = new AlphanumericTable();
    std::string str;
    if(n == 11){
        str = pANT->GetTwoResultByValue(num);
    } else {
        str = pANT->GetResultByValue(num);
    }
    return str;
}

std::__cxx11::string Decoder::ToByteStr(std::vector<int> vec)
{
    int n = vec.size();

    int num = 0;
    for(int i = 0; i < n; i++){
        num = num + int(vec.at(i))*int(pow(2, n-i-1));
    }

    std::string str = "";
    str += (char)num;
    return str;
}

char Decoder::ToUnicodeStr(std::vector<int> vec)
{
    int n = vec.size();
    int num = 0;
    for(int i = 0; i < n; i++){
        num = num + int(vec.at(i))*int(pow(2, n-i-1));
    }

    return (char)num;
}

void Decoder::setImagefile(std::__cxx11::string value)
{
    imagefile = value;
}


}
